﻿using System;
using System.Linq.Expressions;
using System.Web.Mvc;

namespace VietThinks.Web.Mvc
{
    public abstract class HtmlInputElementBuilder : HtmlElementBuilder
    {
        protected object value;

        public object Value { get { return this.value; } }

        public HtmlInputElementBuilder(HtmlHelper htmlHelper)
            : base(htmlHelper)
        {
            this.htmlHelper = HtmlHelper;
        }        

        internal HtmlInputElementBuilder ValueCore(object value)
        {
            this.value = value;

            return this;
        }
    }

    public abstract class HtmlInputElementBuilder<TModel> : HtmlInputElementBuilder
    {
        protected Expression<Func<TModel, object>> expression;        
        protected ValidationMessageBuilder<TModel> validationMessage;
        protected string label = String.Empty;
        protected bool labelAfterField = false;

        public Expression<Func<TModel, object>> Expression { get { return this.expression; } }        

        protected HtmlInputElementBuilder(HtmlHelper htmlHelper, Expression<Func<TModel, object>> expression)
            : base(htmlHelper)
        {
            this.expression = expression;
        }        

        public HtmlInputElementBuilder<TModel> WithValidationMessage(object htmlAttributes)
        {
            this.validationMessage = new ValidationMessageBuilder<TModel>(this).HtmlAttributes(htmlAttributes);

            return this;
        }

        public HtmlInputElementBuilder<TModel> WithValidationMessage()
        {
            this.validationMessage = new ValidationMessageBuilder<TModel>(this);

            return this;
        }

        public HtmlInputElementBuilder<TModel> WithLabel(string label)
        {
            this.label = label;

            return this;
        }

        public HtmlInputElementBuilder<TModel> WithLabel(string label, bool labelAfterField)
        {
            this.label = label;
            this.labelAfterField = labelAfterField;

            return this;
        }

        protected abstract string BuildCore();

        public override string Build()
        {
            if (String.IsNullOrEmpty(this.label))
            {
                return this.BuildCore();
            }

            var labelElement = new HtmlElement("label");

            string labelGenerated = String.Format("{0}{1}{2}",
                                                    labelElement.BuildOpenTag(new { @for = htmlHelper.BuildBindingPath(this.expression).Replace('.', '_') }),
                                                    this.label,
                                                    labelElement.ClosingTag);

            if (this.labelAfterField)
            {
                return String.Format("{1}{0}", labelGenerated, this.BuildCore());    
            }

            return String.Format("{0}{1}", labelGenerated, this.BuildCore());
        }
    }

    public static class HtmlInputElementBuilderExtensions
    {
        public static TBuilder Value<TBuilder>(this TBuilder builder, object value)
            where TBuilder : HtmlInputElementBuilder
        {
            return (TBuilder)builder.ValueCore(value);
        }       
    }    
}
